home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / mozilla-firefox / include / xpcom / nsDoubleHashtable.h < prev    next >
C/C++ Source or Header  |  2006-05-08  |  20KB  |  506 lines

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is Mozilla Communicator client code.
  16.  *
  17.  * The Initial Developer of the Original Code is
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 2002
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  26.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. /**
  39.  * nsDoubleHashtable.h is OBSOLETE. Use nsTHashtable or a derivative instead.
  40.  */
  41.  
  42. #ifndef __nsDoubleHashtable_h__
  43. #define __nsDoubleHashtable_h__
  44.  
  45. #include "pldhash.h"
  46. #include "nscore.h"
  47. #include "nsString.h"
  48. #include "nsHashKeys.h"
  49.  
  50. /*
  51.  * This file provides several major things to make PLDHashTable easier to use:
  52.  * - hash class macros for you to define a hashtable
  53.  * - default key classes to use as superclasses for your entries
  54.  * - empty maps for string, cstring, int and void
  55.  */
  56.  
  57. /*
  58.  * USAGE
  59.  *
  60.  * To use nsDoubleHashtable macros
  61.  * (1) Define an entry class
  62.  * (2) Create the hash class
  63.  * (3) Use the hash class
  64.  *
  65.  * EXAMPLE
  66.  *
  67.  * As an example, let's create a dictionary, a mapping from a string (the word)
  68.  * to the pronunciation and definition of those words.
  69.  *
  70.  * (1) Define an entry class
  71.  *
  72.  * What we want here is an entry class that contains the word, the
  73.  * pronunciation string, and the definition string.  Since we have a string key
  74.  * we can use the standard PLDHashStringEntry class as our base, it will handle
  75.  * the key stuff for us automatically.
  76.  *
  77.  * #include "nsDoubleHashtable.h"
  78.  *
  79.  * // Do NOT ADD VIRTUAL METHODS INTO YOUR ENTRY.  Everything will break.
  80.  * // This is because of the 4-byte pointer C++ magically prepends onto your
  81.  * // entry class.  It interacts very unhappily with PLDHashTable.
  82.  * class DictionaryEntry : public PLDHashStringEntry {
  83.  * public:
  84.  *   DictionaryEntry(const void* aKey) : PLDHashStringEntry(aKey) { }
  85.  *   ~DictionaryEntry() { }
  86.  *   nsString mPronunciation;
  87.  *   nsString mDefinition;
  88.  * }
  89.  *
  90.  * (2) Create the hash class
  91.  *
  92.  * The final hash class you will use in step 3 is defined by 2 macros.
  93.  *
  94.  * DECL_DHASH_WRAPPER(Dictionary, DictionaryEntry, const nsAString&)
  95.  * DHASH_WRAPPER(Dictionary, DictionaryEntry, const nsAString&)
  96.  * 
  97.  * (3) Use the hash class
  98.  *
  99.  * Here is a simple main() that might look up a string:
  100.  *
  101.  * int main(void) {
  102.  *   Dictionary d;
  103.  *   nsresult rv = d.Init(10);
  104.  *   if (NS_FAILED(rv)) return 1;
  105.  *
  106.  *   // Put an entry
  107.  *   DictionaryEntry* a = d.AddEntry(NS_LITERAL_STRING("doomed"));
  108.  *   if (!a) return 1;
  109.  *   a->mDefinition.AssignLiteral("The state you get in when a Mozilla release is pending");
  110.  *   a->mPronunciation.AssignLiteral("doom-d");
  111.  *
  112.  *   // Get the entry
  113.  *   DictionaryEntry* b = d.GetEntry(NS_LITERAL_STRING("doomed"));
  114.  *   printf("doomed: %s\n", NS_ConvertUCS2toUTF8(b->mDefinition).get());
  115.  *
  116.  *   // Entries will be automagically cleaned up when the Dictionary object goes away
  117.  *   return 0;
  118.  * }
  119.  *
  120.  *
  121.  * BONUS POINTS
  122.  *
  123.  * You may wish to extend this class and add helper functions like
  124.  * nsDependentString* GetDefinition(nsAString& aWord).  For example:
  125.  *
  126.  * class MyDictionary : public Dictionary {
  127.  * public:
  128.  *   MyDictionary() { }
  129.  *   // Make SURE you have a virtual destructor
  130.  *   virtual ~myDictionary() { }
  131.  *   nsDependentString* GetDefinition(const nsAString& aWord) {
  132.  *     DictionaryEntry* e = GetEntry(aWord);
  133.  *     if (e) {
  134.  *       // We're returning an nsDependentString here, callers need to delete it
  135.  *       // and it doesn't last long, but at least it doesn't create a copy
  136.  *       return new nsDependentString(e->mDefinition.get());
  137.  *     } else {
  138.  *       return nsnull;
  139.  *     }
  140.  *   }
  141.  *   nsresult PutDefinition(const nsAString& aWord,
  142.  *                          const nsAString& aDefinition,
  143.  *                          const nsAString& aPronunciation) {
  144.  *     DictionaryEntry* e = AddEntry(aWord);
  145.  *     if (!e) {
  146.  *       return NS_ERROR_OUT_OF_MEMORY;
  147.  *     }
  148.  *     e->mDefinition = aDefinition;
  149.  *     e->mPronunciation = aPronunciation;
  150.  *     return NS_OK;
  151.  *   }
  152.  * }
  153.  */
  154.  
  155. /*
  156.  * ENTRY CLASS DEFINITION
  157.  *
  158.  * The simplifications of PLDHashTable all hinge upon the idea of an entry
  159.  * class, which is a class you define, where you store the key and values that
  160.  * you will place in each hash entry.  You must define six methods for an entry
  161.  * (the standard key classes, which you can extend from, define all of these
  162.  * for you except the constructor and destructor):
  163.  *
  164.  * CONSTRUCTOR(const void* aKey)
  165.  * When your entry is constructed it will only be given a pointer to the key.
  166.  *
  167.  * DESTRUCTOR
  168.  * Called when the entry is destroyed (of course).
  169.  *
  170.  * const void* GetKey()
  171.  * Must return a pointer to the key
  172.  *
  173.  * PRBool MatchEntry(const void* aKey) - return true or false depending on
  174.  *        whether the key pointed to by aKey matches this entry
  175.  *
  176.  * static PLDHashNumber HashKey(const void* aKey) - get a hashcode based on the
  177.  *        key (must be the same every time for the same key, but does not have
  178.  *        to be unique)
  179.  *
  180.  * For a small hash that just does key->value, you will often just extend a
  181.  * standard key class and put a value member into it, and have a destructor and
  182.  * constructor--nothing else necessary.
  183.  *
  184.  * See the default key entry classes as example entry classes.
  185.  *
  186.  * NOTES:
  187.  * - Do NOT ADD VIRTUAL METHODS INTO YOUR ENTRY.  Everything will break.
  188.  *   This is because of the 4-byte pointer C++ magically prepends onto your
  189.  *   entry class.  It interacts very unhappily with PLDHashTable.
  190.  */
  191.  
  192. /*
  193.  * PRIVATE HASHTABLE MACROS
  194.  *
  195.  * These internal macros can be used to declare the callbacks for an entry
  196.  * class, but the wrapper class macros call these for you so don't call them.
  197.  */
  198.  
  199. //
  200. // DHASH_CALLBACKS
  201. //
  202. // Define the hashtable callback functions.  Do this in one place only, as you
  203. // will have redundant symbols otherwise.
  204. //
  205. // ENTRY_CLASS: the classname of the entry
  206. //
  207. #define DHASH_CALLBACKS(ENTRY_CLASS)                                          \
  208. PR_STATIC_CALLBACK(const void *)                                              \
  209. ENTRY_CLASS##GetKey(PLDHashTable* table, PLDHashEntryHdr* entry)              \
  210. {                                                                             \
  211.   ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS*, entry);                       \
  212.   return e->GetKey();                                                         \
  213. }                                                                             \
  214. PR_STATIC_CALLBACK(PLDHashNumber)                                             \
  215. ENTRY_CLASS##HashKey(PLDHashTable* table, const void* key)                    \
  216. {                                                                             \
  217.   return ENTRY_CLASS::HashKey(key);                                           \
  218. }                                                                             \
  219. PR_STATIC_CALLBACK(PRBool)                                                    \
  220. ENTRY_CLASS##MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry,    \
  221.                         const void *key)                                      \
  222. {                                                                             \
  223.   const ENTRY_CLASS* e = NS_STATIC_CAST(const ENTRY_CLASS*, entry);           \
  224.   return e->MatchEntry(key);                                                  \
  225. }                                                                             \
  226. PR_STATIC_CALLBACK(void)                                                      \
  227. ENTRY_CLASS##ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)          \
  228. {                                                                             \
  229.   ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS *, entry);                      \
  230.   e->~ENTRY_CLASS();                                                          \
  231. }                                                                             \
  232. PR_STATIC_CALLBACK(PRBool)                                                    \
  233. ENTRY_CLASS##InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,           \
  234.                        const void *key)                                       \
  235. {                                                                             \
  236.   new (entry) ENTRY_CLASS(key);                                               \
  237.   return PR_TRUE;                                                             \
  238. }
  239.  
  240. //
  241. // DHASH_INIT
  242. //
  243. // Initialize hashtable to a certain class.
  244. //
  245. // HASHTABLE: the name of the PLDHashTable variable
  246. // ENTRY_CLASS: the classname of the entry
  247. // NUM_INITIAL_ENTRIES: the number of entry slots the hashtable should start
  248. //                      with
  249. // RV: an nsresult variable to hold the outcome of the initialization.
  250. //     Will be NS_ERROR_OUT_OF_MEMORY if failed, NS_OK otherwise.
  251. //
  252. #define DHASH_INIT(HASHTABLE,ENTRY_CLASS,NUM_INITIAL_ENTRIES,RV)              \
  253. PR_BEGIN_MACRO                                                                \
  254.   static PLDHashTableOps hash_table_ops =                                     \
  255.   {                                                                           \
  256.     PL_DHashAllocTable,                                                       \
  257.     PL_DHashFreeTable,                                                        \
  258.     ENTRY_CLASS##GetKey,                                                      \
  259.     ENTRY_CLASS##HashKey,                                                     \
  260.     ENTRY_CLASS##MatchEntry,                                                  \
  261.     PL_DHashMoveEntryStub,                                                    \
  262.     ENTRY_CLASS##ClearEntry,                                                  \
  263.     PL_DHashFinalizeStub,                                                     \
  264.     ENTRY_CLASS##InitEntry                                                    \
  265.   };                                                                          \
  266.   PRBool isLive = PL_DHashTableInit(&(HASHTABLE),                             \
  267.                                     &hash_table_ops, nsnull,                  \
  268.                                     sizeof(ENTRY_CLASS),                      \
  269.                                     (NUM_INITIAL_ENTRIES));                   \
  270.   if (!isLive) {                                                              \
  271.     (HASHTABLE).ops = nsnull;                                                 \
  272.     RV = NS_ERROR_OUT_OF_MEMORY;                                              \
  273.   } else {                                                                    \
  274.     RV = NS_OK;                                                               \
  275.   }                                                                           \
  276. PR_END_MACRO
  277.  
  278.  
  279. /*
  280.  * WRAPPER CLASS
  281.  *
  282.  * This class handles initialization and destruction of the hashtable
  283.  * (you must call Init() yourself).  It defines these functions:
  284.  *
  285.  * Init(aNumInitialEntries)
  286.  * Initialize the hashtable.  This must be called once, it is only separate
  287.  * from the constructor so that you can get the return value.  You should pass
  288.  * in the number of entries you think the hashtable will typically hold (this
  289.  * will be the amount of space allocated initially so that it will not have to
  290.  * grow).
  291.  *
  292.  * ENTRY_CLASS* GetEntry(aKey):
  293.  * Get the entry referenced by aKey and return a pointer to it.  THIS IS A
  294.  * TEMPORARY POINTER and is only guaranteed to exist until the next time you do
  295.  * an operation on the hashtable.  But you can safely use it until then.
  296.  *
  297.  * Returns nsnull if the entry is not found.
  298.  *
  299.  * ENTRY_CLASS* AddEntry(aKey):
  300.  * Create a new, empty entry and return a pointer to it for you to fill values
  301.  * into.  THIS IS A TEMPORARY POINTER and is only guaranteed to exist until the
  302.  * next time you do an operation on the hashtable.  But you can safely fill it
  303.  * in.
  304.  *
  305.  * Returns nsnull if the entry cannot be created (usually a low memory
  306.  * constraint).
  307.  *
  308.  * void Remove(aKey)
  309.  * Remove the entry referenced by aKey.  If the entry does not exist, nothing
  310.  * will happen.
  311.  *
  312.  *
  313.  * DECL_DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE)
  314.  *
  315.  * Declare the hash class but do not define the functions.
  316.  *
  317.  * CLASSNAME: the name of the class to declare.
  318.  * ENTRY_CLASS: the class of the entry struct.
  319.  * KEY_TYPE: the name of the key type for GetEntry and AddEntry.
  320.  *
  321.  *
  322.  * DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE)
  323.  *
  324.  * Define the functions for the hash class.
  325.  *
  326.  * CLASSNAME: the name of the class to declare.
  327.  * ENTRY_CLASS: the class of the entry struct.
  328.  * KEY_TYPE: the name of the key type for GetEntry and AddEntry.
  329.  *
  330.  *
  331.  * CAVEATS:
  332.  * - You may have only *one* wrapper class per entry class.
  333.  */
  334.  
  335. #define DECL_DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE)                    \
  336. class DHASH_EXPORT CLASSNAME {                                                \
  337. public:                                                                       \
  338.   CLASSNAME();                                                                \
  339.   ~CLASSNAME();                                                               \
  340.   nsresult Init(PRUint32 aNumInitialEntries);                                 \
  341.   ENTRY_CLASS* GetEntry(const KEY_TYPE aKey);                                 \
  342.   ENTRY_CLASS* AddEntry(const KEY_TYPE aKey);                                 \
  343.   void Remove(const KEY_TYPE aKey);                                           \
  344.   PLDHashTable mHashTable;                                                    \
  345. };
  346.  
  347. #define DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE)                         \
  348. DHASH_CALLBACKS(ENTRY_CLASS)                                                  \
  349. CLASSNAME::CLASSNAME() {                                                      \
  350.   mHashTable.ops = nsnull;                                                    \
  351. }                                                                             \
  352. CLASSNAME::~CLASSNAME() {                                                     \
  353.   if (mHashTable.ops) {                                                       \
  354.     PL_DHashTableFinish(&mHashTable);                                         \
  355.   }                                                                           \
  356. }                                                                             \
  357. nsresult CLASSNAME::Init(PRUint32 aNumInitialEntries) {                       \
  358.   if (!mHashTable.ops) {                                                      \
  359.     nsresult rv;                                                              \
  360.     DHASH_INIT(mHashTable,ENTRY_CLASS,aNumInitialEntries,rv);                 \
  361.     return rv;                                                                \
  362.   }                                                                           \
  363.   return NS_OK;                                                               \
  364. }                                                                             \
  365. ENTRY_CLASS* CLASSNAME::GetEntry(const KEY_TYPE aKey) {                       \
  366.   ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS*,                               \
  367.                                   PL_DHashTableOperate(&mHashTable, &aKey,    \
  368.                                                        PL_DHASH_LOOKUP));     \
  369.   return PL_DHASH_ENTRY_IS_BUSY(e) ? e : nsnull;                              \
  370. }                                                                             \
  371. ENTRY_CLASS* CLASSNAME::AddEntry(const KEY_TYPE aKey) {                       \
  372.   return NS_STATIC_CAST(ENTRY_CLASS*,                                         \
  373.                         PL_DHashTableOperate(&mHashTable, &aKey,              \
  374.                                              PL_DHASH_ADD));                  \
  375. }                                                                             \
  376. void CLASSNAME::Remove(const KEY_TYPE aKey) {                                 \
  377.   PL_DHashTableOperate(&mHashTable, &aKey, PL_DHASH_REMOVE);                  \
  378. }
  379.  
  380. /*
  381.  * STANDARD KEY ENTRY CLASSES
  382.  *
  383.  * We have declared some standard key classes for you to make life a little
  384.  * easier.  These include string, int and void* keys.  You can extend these
  385.  * and add value data members to make a working hash entry class with your
  386.  * values.
  387.  *
  388.  * PLDHashStringEntry:  nsAString
  389.  * PLDHashCStringEntry: nsACString
  390.  * PLDHashInt32Entry:   PRInt32
  391.  * PLDHashVoidEntry:    void*
  392.  *
  393.  * As a short example, if you want to make a class that maps int to string,
  394.  * you could do:
  395.  *
  396.  * class MyIntStringEntry : public PLDHashInt32Entry
  397.  * {
  398.  * public:
  399.  *   MyIntStringEntry(const void* aKey) : PLDHashInt32Entry(aKey) { }
  400.  *   ~MyIntStringEntry() { };
  401.  *   nsString mMyStr;
  402.  * };
  403.  *
  404.  * XXX It could be advisable (unless COW strings ever happens) to have a
  405.  * PLDHashDependentStringEntry
  406.  */
  407.  
  408. //
  409. // String-key entry
  410. //
  411. class NS_COM PLDHashStringEntry : public PLDHashEntryHdr
  412. {
  413. public:
  414.   PLDHashStringEntry(const void* aKey) :
  415.     mKey(*NS_STATIC_CAST(const nsAString*, aKey)) { }
  416.   ~PLDHashStringEntry() { }
  417.  
  418.   const void* GetKey() const {
  419.     return NS_STATIC_CAST(const nsAString*, &mKey);
  420.   }
  421.   static PLDHashNumber HashKey(const void* key) {
  422.     return HashString(*NS_STATIC_CAST(const nsAString*, key));
  423.   }
  424.   PRBool MatchEntry(const void* key) const {
  425.     return NS_STATIC_CAST(const nsAString*, key)->Equals(mKey);
  426.   }
  427.  
  428.   const nsString mKey;
  429. };
  430.  
  431. //
  432. // CString-key entry
  433. //
  434. class NS_COM PLDHashCStringEntry : public PLDHashEntryHdr
  435. {
  436. public:
  437.   PLDHashCStringEntry(const void* aKey) :
  438.     mKey(*NS_STATIC_CAST(const nsACString*, aKey)) { }
  439.   ~PLDHashCStringEntry() { }
  440.  
  441.   const void* GetKey() const {
  442.     return NS_STATIC_CAST(const nsACString*, &mKey);
  443.   }
  444.   static PLDHashNumber HashKey(const void* key) {
  445.     return HashString(*NS_STATIC_CAST(const nsACString*, key));
  446.   }
  447.   PRBool MatchEntry(const void* key) const {
  448.     return NS_STATIC_CAST(const nsACString*, key)->Equals(mKey);
  449.   }
  450.  
  451.   const nsCString mKey;
  452. };
  453.  
  454. //
  455. // Int-key entry
  456. //
  457. class NS_COM PLDHashInt32Entry : public PLDHashEntryHdr
  458. {
  459. public:
  460.   PLDHashInt32Entry(const void* aKey) :
  461.     mKey(*(NS_STATIC_CAST(const PRInt32*, aKey))) { }
  462.   ~PLDHashInt32Entry() { }
  463.  
  464.   const void* GetKey() const {
  465.     return NS_STATIC_CAST(const PRInt32*, &mKey);
  466.   }
  467.   static PLDHashNumber HashKey(const void* key) {
  468.     return *NS_STATIC_CAST(const PRInt32*, key);
  469.   }
  470.   PRBool MatchEntry(const void* key) const {
  471.     return *(NS_STATIC_CAST(const PRInt32*, key)) == mKey;
  472.   }
  473.  
  474.   const PRInt32 mKey;
  475. };
  476.  
  477.  
  478. //
  479. // Void-key entry
  480. //
  481. class NS_COM PLDHashVoidEntry : public PLDHashEntryHdr
  482. {
  483. public:
  484.   PLDHashVoidEntry(const void* aKey) :
  485.     mKey(*(const void**)aKey) { }
  486.   ~PLDHashVoidEntry() { }
  487.  
  488.   const void* GetKey() const {
  489.     return (const void**)&mKey;
  490.   }
  491.   static PLDHashNumber HashKey(const void* key) {
  492.     return PLDHashNumber(NS_PTR_TO_INT32(*(const void**)key)) >> 2;
  493.   }
  494.   PRBool MatchEntry(const void* key) const {
  495.     return *(const void**)key == mKey;
  496.   }
  497.  
  498.   const void* mKey;
  499. };
  500.  
  501.  
  502. #define DHASH_EXPORT
  503.  
  504.  
  505. #endif
  506.